/**
 * This file is part of JNotifyOSD.
 *
 * JNotifyOSD is free software: you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * JNotifyOSD is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with JNotifyOSD. If not, see <http://www.gnu.org/licenses/>.
 */

package notifyosd;

import java.util.EnumMap;

/**
 * Handler for a On-screen notification
 * @author Giulio Franco <g.franco9@studenti.unisa.it>
 */
public class NativeNotification implements Notification {
    private static final EnumMap<Urgency, Integer> PRIORITY;
    static {
        PRIORITY = new EnumMap<Urgency, Integer>(Urgency.class);
        PRIORITY.put(Urgency.LOW, getLowPrio());
        PRIORITY.put(Urgency.NORMAL, getNorPrio());
        PRIORITY.put(Urgency.CRITICAL, getCriPrio());
    }
    
    //Used by native code
    private long nativeNotification;
    
    private String title;
    private String body;
    private String icon;
    private String category = null;
    private int timeout = -1;
    private Urgency urgency = null;
    
    /**
     * Initializes a notification
     * @param title NativeNotification title
     * @param body  NativeNotification body (optional)
     * @param icon  NativeNotification icon (optional)
     */
    NativeNotification(String title, String body, String icon) {
        if (title == null)
            throw new NullPointerException("title cannot be null");
        nativeInit(title, body, icon);
        this.title = title;
        this.body = (body == null) ? "" : body;
        this.icon = icon;
    }
    
    /**
     * Gets the text
     * @return Text of the notification
     */
    public String getBody() {
        return body;
    }

    /**
     * Sets the text
     * @param body New text for the notification
     */
    public void setBody(String body) {
        body = (body == null) ? "" : body;
        nativeUpdate(title, this.body = body, icon);
    }

    /**
     * Gets the category
     * @return Category of the notification
     */
    public String getCategory() {
        return category;
    }

    /**
     * Sets the category
     * @param category New category
     */
    public void setCategory(String category) {
        nativeSetCategory(this.category = category);
    }

    /**
     * Gets the icon
     * @return Path of the icon
     */
    public String getIcon() {
        return icon;
    }

    /**
     * Sets the icon
     * @param icon Path of the new icon
     */
    public void setIcon(String icon) {
        nativeUpdate(title, body, this.icon = icon);
    }

    /**
     * Gets the timeout
     * @return Time the notification should be displayed for (milliseconds)
     */
    public int getTimeout() {
        return timeout;
    }

    /**
     * Sets the timeout
     * @param timeout Time the notification should be displayed for (millisec.)
     */
    public void setTimeout(int timeout) {
        nativeSetTimeout(this.timeout = timeout);
    }

    /**
     * Gets the title
     * @return Title of the notification
     */
    public String getTitle() {
        return title;
    }

    /**
     * Sets the title
     * @param title Title of the notification
     * @throws NullPointerException if title is null
     */
    public void setTitle(String title) {
        if (title == null)
            throw new NullPointerException("title cannot be null");
        nativeUpdate(this.title = title, body, icon);
    }

    /**
     * Gets the urgency
     * @return Urgency of the notification
     */
    public Urgency getUrgency() {
        return urgency;
    }

    /**
     * Sets the urgency
     * @param urgency Urgency of the notification
     */
    public void setUrgency(Urgency urgency) {
        this.urgency = urgency;
        nativeSetUrgency(PRIORITY.get(urgency));
    }
    
    @Override
    protected void finalize() throws Throwable {
        nativeDestroy();
        super.finalize();
    }
    
    /**
     * Displays the notification
     * The notification will be hidden automatically
     * after at most {@link #getTimeout()} milliseconds.
     */
    public void show() {
        nativeShow();
    }
    
    /**
     * Hides the notification.
     */
    public void hide() {
        nativeHide();
    }
    
    private native void nativeDestroy();
    private native void nativeHide();
    private native void nativeInit(String title, String body, String icon);
    private native void nativeSetCategory(String category);
    private native void nativeSetTimeout(int timeout);
    private native void nativeSetUrgency(int urgency);
    private native void nativeShow();
    private native void nativeUpdate(String title, String body, String icon);
    private static native int getLowPrio();
    private static native int getNorPrio();
    private static native int getCriPrio();
}
